2023/12/232355字符

切片类型(动态数组)

  • 切片的本质就是指向了一个底层数组,随着容量的增大而不停的改变新的底层数组,从而实现扩容;
  • 如果已经有了数值,我们也可以直接创建切片。
package main

import "fmt"

func main() {
    var sli1 = make([]int, 3, 8)

    fmt.Println(sli1)  //--> [0 0 0]
    fmt.Println(len(sli1), cap(sli1))  //--> 3 8

    var sli2 = append(sli1, 3, 4)
    fmt.Println(sli2)  //--> [0 0 0 3 4]

    var sli3 = [] int{5, 6}  //--> 不指定长度是一个 slice
    var sli4 = append(sli2, sli3...)
    fmt.Println(sli4)  //--> [0 0 0 3 4 5 6]
}

内存分析

切片的每一项是引用关系,改变数据,被引用切片也相应做出改变

package main

import "fmt"

func main() {
    arr := [10]int{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }
    s1 := arr[:5]
    s2 := arr[3:8]
    s3 := arr[5:]
    s4 := arr[:]

    fmt.Printf("%p, %p, %p\n", &arr, s1, s4)  // arr, s1, s4 指向同一个地址

    fmt.Println(len(s1), cap(s1))  //--> 5 10
    fmt.Println(len(s2), cap(s2))  //--> 5 7
    fmt.Println(len(s3), cap(s3))  //--> 5 5 
    fmt.Println(len(s4), cap(s4))  //--> 10 10

    // 操作数组,切片数据发生改变
    arr[3] = 100
    fmt.Println(s1, s2, s3, s4)  //--> 1 2 3 100 5] [100 5 6 7 8] [6 7 8 9 10] [1 2 3 100 5 6 7 8 9 10]

    // 操作切片,数组数据也会被更改
    s1[4] = 200
    fmt.Println(arr)  //--> [1 2 3 100 200 6 7 8 9 10]

    // 切片添加内容,数组也会被改变
    s1 = append(s1, 1, 1, 1)
    fmt.Println(arr, s1, s2)  //--> [1 2 3 100 200 1 1 1 9 10] [1 2 3 100 200 1 1 1] [100 200 1 1 1]

    // 超出数组长度,go 会新开辟一个数组地址,与原先的数组就没关系了
    s1 = append(s1, 2, 2, 2, 2, 2)
    fmt.Println(arr, s1)  //--> [1 2 3 100 200 1 1 1 9 10] [1 2 3 100 200 1 1 1 2 2 2 2 2]
    fmt.Printf("%p, %p\n", &arr, s1)  //--> 0xc00001c050, 0xc000104000

}

copy 深度克隆

package main

import "fmt"

func main() {
    s1 := []int{1, 2, 3, 4}
    s2 := []int{5, 6, 7}

    copy(s1, s2)
    fmt.Println(s1, s2)  //--> [5 6 7 4] [5 6 7]

    s3 := []int{1, 2, 3, 4}
    s4 := []int{5, 6, 7}
    copy(s4, s3[2:])
    fmt.Println(s3, s4)  //--> [1 2 3 4] [3 4 7]

}

排序

package main

import (
    "fmt"
    "sort"
)

func main() {
    var sli = []int{ 3, 1, 6, 9, 4 }
    sort.Ints(sli)
    fmt.Println(sli)  //--> [1 3 4 6 9]
}